<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="theme-color" content="#0078E7"><meta name="author" content="爱肖彤真是太好了"><meta name="copyright" content="爱肖彤真是太好了"><meta name="generator" content="Hexo 5.1.1"><meta name="theme" content="hexo-theme-yun"><title>django知识点扩展 | 工藤旧二の博客</title><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@900&amp;display=swap" media="none" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/star-markdown-css@0.1.19/dist/yun/yun-markdown.min.css"><script src="//at.alicdn.com/t/font_1140697_stqaphw3j4.js" async></script><script src="https://cdn.jsdelivr.net/npm/scrollreveal/dist/scrollreveal.min.js" defer></script><script>document.addEventListener("DOMContentLoaded", () => {
  [".post-card",".post-content img"].forEach((target)=> {
    ScrollReveal().reveal(target);
  })
});
</script><link rel="shortcut icon" type="image/svg+xml" href="/task/yun.ico"><link rel="mask-icon" href="/task/yun.ico" color="#0078E7"><link rel="alternate icon" href="/yun.ico"><link rel="preload" href="/task/css/hexo-theme-yun.css" as="style"><link rel="preload" href="/task/js/utils.js" as="script"><link rel="preload" href="/task/js/hexo-theme-yun.js" as="script"><link rel="prefetch" href="/task/js/sidebar.js" as="script"><link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin><link rel="stylesheet" href="/task/css/hexo-theme-yun.css"><link rel="alternate" href="/task/atom.xml" title="工藤旧二の博客" type="application/atom+xml"><script id="yun-config">
    const Yun = window.Yun || {};
    window.CONFIG = {"root":"/task/","title":"工藤旧二の博客","version":"0.9.7","anonymous_image":"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/avatar/none.jpg","say":{"api":"https://v1.hitokoto.cn","hitokoto":true},"local_search":{"path":"/task/search.xml"},"fireworks":{"colors":["102, 167, 221","62, 131, 225","33, 78, 194"]}};
  </script><script>(function(){
  var bp = document.createElement('script');
  var curProtocol = window.location.protocol.split(':')[0];
  if (curProtocol === 'https') {
    bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
  }
  else {
    bp.src = 'http://push.zhanzhang.baidu.com/push.js';
  }
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(bp, s);
})();</script><meta name="description" content="django 知识点扩展一、模型部分1 关于ForeignKey1.1 级联在django2版本以上，外键关联的数据需要设置级联更新 xxx &#x3D; models.ForeignKey(关联的表,on_delete&#x3D;model.CASCADE) # 级联操作需要注意，如果是一对一的关联，那没问题应该级联删除 # 但如果是一对多，删除了一个出版社，就把这个出版社的所有书都删了，显然不合理，因为书和出版社">
<meta property="og:type" content="article">
<meta property="og:title" content="django知识点扩展">
<meta property="og:url" content="http://huang_zhao.gitee.io/task/2021/05/15/python/%E6%A1%86%E6%9E%B6/django%20%E7%9F%A5%E8%AF%86%E7%82%B9%E6%89%A9%E5%B1%95/index.html">
<meta property="og:site_name" content="工藤旧二の博客">
<meta property="og:description" content="django 知识点扩展一、模型部分1 关于ForeignKey1.1 级联在django2版本以上，外键关联的数据需要设置级联更新 xxx &#x3D; models.ForeignKey(关联的表,on_delete&#x3D;model.CASCADE) # 级联操作需要注意，如果是一对一的关联，那没问题应该级联删除 # 但如果是一对多，删除了一个出版社，就把这个出版社的所有书都删了，显然不合理，因为书和出版社">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-05-15T07:11:23.000Z">
<meta property="article:modified_time" content="2021-06-27T09:20:34.000Z">
<meta property="article:author" content="爱肖彤真是太好了">
<meta property="article:tag" content="django">
<meta property="article:tag" content="python">
<meta name="twitter:card" content="summary"><script src="/task/js/ui/mode.js"></script><link rel="stylesheet" href="/task/css/prism.css" type="text/css"></head><body><script defer src="https://cdn.jsdelivr.net/npm/animejs@latest/anime.min.js"></script><script defer src="/task/js/ui/fireworks.js"></script><canvas class="fireworks"></canvas><div class="container"><a class="sidebar-toggle hty-icon-button" id="menu-btn"><div class="hamburger hamburger--spin" type="button"><span class="hamburger-box"><span class="hamburger-inner"></span></span></div></a><div class="sidebar-toggle sidebar-overlay"></div><aside class="sidebar"><script src="/task/js/sidebar.js"></script><ul class="sidebar-nav"><li class="sidebar-nav-item sidebar-nav-toc hty-icon-button sidebar-nav-active" data-target="post-toc-wrap" title="文章目录"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-list-ordered"></use></svg></li><li class="sidebar-nav-item sidebar-nav-overview hty-icon-button" data-target="site-overview-wrap" title="站点概览"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-passport-line"></use></svg></li></ul><div class="sidebar-panel" id="site-overview-wrap"><div class="site-info fix-top"><a class="site-author-avatar" href="/task/about/" title="爱肖彤真是太好了"><img width="96" loading="lazy" src="/task/Yun.png" alt="爱肖彤真是太好了"></a><div class="site-author-name"><a href="/task/about/">爱肖彤真是太好了</a></div><a class="site-name" href="/task/about/site.html">工藤旧二の博客</a><sub class="site-subtitle"></sub><div class="site-desciption"></div></div><nav class="site-state"><a class="site-state-item hty-icon-button icon-home" href="/task/" title="首页"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-home-4-line"></use></svg></span></a><div class="site-state-item"><a href="/task/archives/" title="归档"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-archive-line"></use></svg></span><span class="site-state-item-count">57</span></a></div><div class="site-state-item"><a href="/task/categories/" title="分类"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-folder-2-line"></use></svg></span><span class="site-state-item-count">2</span></a></div><div class="site-state-item"><a href="/task/tags/" title="标签"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="site-state-item-count">50</span></a></div><a class="site-state-item hty-icon-button" target="_blank" rel="noopener" href="https://yun.yunyoujun.cn" title="文档"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-settings-line"></use></svg></span></a></nav><hr style="margin-bottom:0.5rem"><div class="links-of-author"><a class="links-of-author-item hty-icon-button" rel="noopener" title="RSS" target="_blank" style="color:orange"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-rss-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="QQ" target="_blank" style="color:#12B7F5"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-qq-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="GitHub" target="_blank" style="color:#6e5494"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-github-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="微博" target="_blank" style="color:#E6162D"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-weibo-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="豆瓣" target="_blank" style="color:#007722"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-douban-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://music.163.com/#/user/home?id=552858287" title="网易云音乐" target="_blank" style="color:#C20C0C"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-netease-cloud-music-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="知乎" target="_blank" style="color:#0084FF"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-zhihu-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://space.bilibili.com/15081363" title="哔哩哔哩" target="_blank" style="color:#FF8EB3"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-bilibili-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="Twitter" target="_blank" style="color:#1da1f2"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-twitter-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="Telegram Channel" target="_blank" style="color:#0088CC"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-telegram-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="E-Mail" target="_blank" style="color:#8E71C1"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-mail-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="Travelling" target="_blank" style="color:var(--hty-text-color)"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-send-plane-2-line"></use></svg></a></div><hr style="margin:0.5rem 1rem"><div class="links"><a class="links-item hty-icon-button" href="/task/links/" title="我的小伙伴们" style="color:dodgerblue"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-genderless-line"></use></svg></a></div><br><a class="links-item hty-icon-button" id="toggle-mode-btn" href="javascript:;" title="Mode" style="color: #f1cb64"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-contrast-2-line"></use></svg></a></div><div class="sidebar-panel sidebar-panel-active" id="post-toc-wrap"><div class="post-toc"><div class="post-toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#django-%E7%9F%A5%E8%AF%86%E7%82%B9%E6%89%A9%E5%B1%95"><span class="toc-text">django 知识点扩展</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81%E6%A8%A1%E5%9E%8B%E9%83%A8%E5%88%86"><span class="toc-text">一、模型部分</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E5%85%B3%E4%BA%8EForeignKey"><span class="toc-text">1 关于ForeignKey</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1-%E7%BA%A7%E8%81%94"><span class="toc-text">1.1 级联</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2-%E5%8F%82%E6%95%B0"><span class="toc-text">1.2 参数</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E5%85%B3%E4%BA%8E%E5%86%85%E9%83%A8%E7%B1%BB"><span class="toc-text">2 关于内部类</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81%E8%A7%86%E5%9B%BE%E5%87%BD%E6%95%B0%E9%83%A8%E5%88%86"><span class="toc-text">二、视图函数部分</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E5%85%B3%E4%BA%8Emarkdown%E4%BD%BF%E7%94%A8"><span class="toc-text">1 关于markdown使用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81queryset%E5%AF%B9%E8%B1%A1"><span class="toc-text">2、queryset对象</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-%E5%8F%AF%E5%88%87%E7%89%87"><span class="toc-text">2.1 可切片</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-%E5%8F%AF%E8%BF%AD%E4%BB%A3"><span class="toc-text">2.2 可迭代</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3-%E6%83%B0%E6%80%A7%E6%9F%A5%E8%AF%A2"><span class="toc-text">2.3 惰性查询</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-4-%E7%BC%93%E5%AD%98%E6%9C%BA%E5%88%B6%EF%BC%9F"><span class="toc-text">2.4 缓存机制？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-5-exists-%E4%B8%8Eiterator-%E6%96%B9%E6%B3%95"><span class="toc-text">2.5 exists()与iterator()方法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-6-orm%E9%A2%9D%E5%A4%96%E6%96%B9%E6%B3%95"><span class="toc-text">2.6 orm额外方法</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-extra"><span class="toc-text">3 extra</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-1%E5%8F%82%E6%95%B0%E4%B9%8Bselect"><span class="toc-text">4.1参数之select</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-2%E5%8F%82%E6%95%B0%E4%B9%8Bwhere-tables"><span class="toc-text">4.2参数之where &#x2F; tables</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%89%E3%80%81%E8%B7%AF%E7%94%B1%E9%83%A8%E5%88%86"><span class="toc-text">三、路由部分</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-url%E5%92%8Cpath%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-text">1 url和path的区别</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9B%9B%E3%80%81%E6%A8%A1%E7%89%88%E9%83%A8%E5%88%86"><span class="toc-text">四、模版部分</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-xss%E6%94%BB%E5%87%BB"><span class="toc-text">1 xss攻击</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%94%E3%80%81settings"><span class="toc-text">五、settings</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E6%9A%B4%E9%9C%B2"><span class="toc-text">1 静态资源暴露</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E9%A1%B9%E7%9B%AE%E4%BF%AE%E6%94%B9%E6%88%90%E4%B8%AD%E6%96%87"><span class="toc-text">2 项目修改成中文</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%85%AD%E3%80%81RBAC%EF%BC%9A%E5%9F%BA%E4%BA%8E%E8%A7%92%E8%89%B2%E7%9A%84%E6%9D%83%E9%99%90%E6%8E%A7%E5%88%B6%EF%BC%88django%E5%86%85%E7%BD%AE%E7%9A%84auth%E4%BD%93%E7%B3%BB%EF%BC%89"><span class="toc-text">六、RBAC：基于角色的权限控制（django内置的auth体系）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%83%E3%80%81django%E7%9A%84%E7%BC%93%E5%AD%98"><span class="toc-text">七、django的缓存</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E7%BC%93%E5%AD%986%E4%B8%AD%E9%85%8D%E7%BD%AE%E4%BD%8D%E7%BD%AE"><span class="toc-text">1 缓存6中配置位置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E7%BC%93%E5%AD%98%E5%BA%94%E7%94%A8"><span class="toc-text">2 缓存应用</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-%E8%A7%86%E5%9B%BE%E4%B8%AD%E4%BD%BF%E7%94%A8%E7%BC%93%E5%AD%98"><span class="toc-text">2.1 视图中使用缓存</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-%E5%85%A8%E5%B1%80%E4%BD%BF%E7%94%A8%E7%BC%93%E5%AD%98"><span class="toc-text">2.2 全局使用缓存</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3-%E5%B1%80%E9%83%A8%E8%A7%86%E5%9B%BE%E7%BC%93%E5%AD%98"><span class="toc-text">2.3 局部视图缓存</span></a></li></ol></li></ol></li></ol></li></ol></div></div></div></aside><main class="sidebar-translate" id="content"><div id="post"><article class="post-block" itemscope itemtype="https://schema.org/Article"><link itemprop="mainEntityOfPage" href="http://huang_zhao.gitee.io/task/task/2021/05/15/python/%E6%A1%86%E6%9E%B6/django%20%E7%9F%A5%E8%AF%86%E7%82%B9%E6%89%A9%E5%B1%95/"><span hidden itemprop="author" itemscope itemtype="https://schema.org/Person"><meta itemprop="name" content="爱肖彤真是太好了"><meta itemprop="description"></span><span hidden itemprop="publisher" itemscope itemtype="https://schema.org/Organization"><meta itemprop="name" content="工藤旧二の博客"></span><header class="post-header"><h1 class="post-title" itemprop="name headline">django知识点扩展</h1><div class="post-meta"><div class="post-time" style="display:block"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-calendar-line"></use></svg></span> <time title="创建时间：2021-05-15 15:11:23" itemprop="dateCreated datePublished" datetime="2021-05-15T15:11:23+08:00">2021-05-15</time><span class="post-meta-divider">-</span><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-calendar-2-line"></use></svg></span> <time title="修改时间：2021-06-27 17:20:34" itemprop="dateModified" datetime="2021-06-27T17:20:34+08:00">2021-06-27</time></div><span class="post-count"><span class="post-symbolcount"><span class="post-meta-item-icon" title="本文字数"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-file-word-line"></use></svg></span> <span title="本文字数">3.6k</span><span class="post-meta-divider">-</span><span class="post-meta-item-icon" title="阅读时长"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-timer-line"></use></svg></span> <span title="阅读时长">14m</span></span></span><span class="post-busuanzi"><span class="post-meta-divider">-</span><span class="post-meta-item-icon" title="阅读次数"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-eye-line"></use></svg> <span id="busuanzi_value_page_pv"></span></span></span><div class="post-classify"><span class="post-category"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-folder-line"></use></svg></span> <span itemprop="about" itemscope itemtype="https://schema.org/Thing"><a class="category" href="/task/categories/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/" style="--text-color:var(--hty-text-color)" itemprop="url" rel="index"><span itemprop="text">技术分享</span></a></span></span><span class="post-tag"><span class="post-meta-divider">-</span><a class="tag" href="/task/tags/django/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">django</span></a><a class="tag" href="/task/tags/python/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">python</span></a></span></div></div></header><section class="post-body" itemprop="articleBody"><div class="post-content markdown-body" style="--smc-primary:#0078E7;"><h1 id="django-知识点扩展"><a href="#django-知识点扩展" class="headerlink" title="django 知识点扩展"></a>django 知识点扩展</h1><h2 id="一、模型部分"><a href="#一、模型部分" class="headerlink" title="一、模型部分"></a>一、模型部分</h2><h3 id="1-关于ForeignKey"><a href="#1-关于ForeignKey" class="headerlink" title="1 关于ForeignKey"></a>1 关于ForeignKey</h3><h4 id="1-1-级联"><a href="#1-1-级联" class="headerlink" title="1.1 级联"></a>1.1 级联</h4><p>在django2版本以上，外键关联的数据需要设置级联更新</p>
<pre class=" language-python"><code class="language-python">xxx <span class="token operator">=</span> models<span class="token punctuation">.</span>ForeignKey<span class="token punctuation">(</span>关联的表<span class="token punctuation">,</span>on_delete<span class="token operator">=</span>model<span class="token punctuation">.</span>CASCADE<span class="token punctuation">)</span>
<span class="token comment" spellcheck="true"># 级联操作需要注意，如果是一对一的关联，那没问题应该级联删除</span>
<span class="token comment" spellcheck="true"># 但如果是一对多，删除了一个出版社，就把这个出版社的所有书都删了，显然不合理，因为书和出版社只是逻辑联系，不是真的物理关联</span>
<span class="token comment" spellcheck="true"># 所以通常我们会断开一对多的关联表</span>
 publish <span class="token operator">=</span> models<span class="token punctuation">.</span>ForeignKey<span class="token punctuation">(</span>to<span class="token operator">=</span><span class="token string">'Publish'</span><span class="token punctuation">,</span>on_delete<span class="token operator">=</span>models<span class="token punctuation">.</span>DO_NOTHING<span class="token punctuation">,</span>db_constraint<span class="token operator">=</span><span class="token boolean">False</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true"># db_constraint=False 表示这个外键只有逻辑关联，没有实质的关联</span>
<span class="token comment" spellcheck="true"># 级联也应当修改</span>
on_delete <span class="token operator">=</span> models<span class="token punctuation">.</span>DO_NOTHING <span class="token comment" spellcheck="true"># 删除出版社的时候，书表什么都不做</span>
on_delete <span class="token operator">=</span> models<span class="token punctuation">.</span>CASCADE <span class="token comment" spellcheck="true"># 级联删除</span>
on_delete <span class="token operator">=</span> models<span class="token punctuation">.</span>SET_NULL <span class="token comment" spellcheck="true"># 前提是这个字段可以为空</span>
on_delete <span class="token operator">=</span> models<span class="token punctuation">.</span>SET_DEFAULT <span class="token comment" spellcheck="true"># 前提是有默认值</span></code></pre>
<h4 id="1-2-参数"><a href="#1-2-参数" class="headerlink" title="1.2 参数"></a>1.2 参数</h4><pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># to 设置要关联的表</span>
<span class="token comment" spellcheck="true"># to_field 设置要关联表的字段</span>
<span class="token comment" spellcheck="true"># related_name 反向查询的时候替代原来的‘表名_set’</span>
<span class="token comment" spellcheck="true"># db_constraint 是否在数据库中创建外键约束，默认为True</span></code></pre>
<h3 id="2-关于内部类"><a href="#2-关于内部类" class="headerlink" title="2 关于内部类"></a>2 关于内部类</h3><p>内部类class Meta提供模型的元数据，元数据不属于任何字段的东西，是对整张表的描述</p>
<p>具体拥有的参数</p>
<ul>
<li><p>ordering 排序选项</p>
<ul>
<li><pre class=" language-python"><code class="language-python">ordering <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token string">'pk'</span><span class="token punctuation">,</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true"># 需要注意排序的根据是一个元组，所以如果只有一个根据就要加逗号，排序如果出现重复就会根据第二个元素的排序依据进行排序</span></code></pre>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>db_table 数据库表名</p>
<ul>
<li><pre class=" language-python"><code class="language-python">db_table <span class="token operator">=</span> <span class="token string">'数据库表名'</span>
<span class="token comment" spellcheck="true"># 注意此处修改表名是真实的在数据库中的表名被修改了，所以需要重新进行数据迁移</span></code></pre>
</li>
</ul>
</li>
<li><p>verbose_name_plural/verbose_name 单复数名称</p>
<ul>
<li>这是在admin后台管理的时候显示的名称，复数后缀会在中文后加s通常用中文的话就用单数</li>
</ul>
</li>
</ul>
<p><strong>其他相关字段</strong></p>
<pre class=" language-python"><code class="language-python"><span class="token keyword">class</span> <span class="token class-name">UserInfo</span><span class="token punctuation">(</span>models<span class="token punctuation">.</span>Model<span class="token punctuation">)</span><span class="token punctuation">:</span>
        nid <span class="token operator">=</span> models<span class="token punctuation">.</span>AutoField<span class="token punctuation">(</span>primary_key<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span>
        username <span class="token operator">=</span> models<span class="token punctuation">.</span>CharField<span class="token punctuation">(</span>max_length<span class="token operator">=</span><span class="token number">32</span><span class="token punctuation">)</span>

        <span class="token keyword">class</span> <span class="token class-name">Meta</span><span class="token punctuation">:</span>
            <span class="token comment" spellcheck="true"># 设置成虚拟表，通常用于通用表，添加一些每个表必有的字段，让其他表继承</span>
            abstract <span class="token operator">=</span> <span class="token boolean">True</span>
            <span class="token comment" spellcheck="true"># 数据库中生成的表名称 默认 app名称 + 下划线 + 类名</span>
            db_table <span class="token operator">=</span> <span class="token string">"table_name"</span>

            <span class="token comment" spellcheck="true"># 联合索引</span>
            index_together <span class="token operator">=</span> <span class="token punctuation">[</span>
                <span class="token punctuation">(</span><span class="token string">"pub_date"</span><span class="token punctuation">,</span> <span class="token string">"deadline"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token punctuation">]</span>

            <span class="token comment" spellcheck="true"># 联合唯一索引</span>
            unique_together <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">"driver"</span><span class="token punctuation">,</span> <span class="token string">"restaurant"</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token punctuation">)</span>

            ordering <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token string">'name'</span><span class="token punctuation">,</span><span class="token punctuation">)</span>

            <span class="token comment" spellcheck="true"># admin中显示的表名称</span>
            verbose_name<span class="token operator">=</span><span class="token string">'哈哈'</span>

            <span class="token comment" spellcheck="true"># verbose_name加s</span>
            verbose_name_plural<span class="token operator">=</span>verbose_name

</code></pre>
<h2 id="二、视图函数部分"><a href="#二、视图函数部分" class="headerlink" title="二、视图函数部分"></a>二、视图函数部分</h2><h3 id="1-关于markdown使用"><a href="#1-关于markdown使用" class="headerlink" title="1 关于markdown使用"></a>1 关于markdown使用</h3><pre class=" language-python"><code class="language-python"><span class="token keyword">import</span> markdown

<span class="token comment" spellcheck="true"># 将markdown语法渲染成html样式</span>
    article<span class="token punctuation">.</span>body <span class="token operator">=</span> markdown<span class="token punctuation">.</span>markdown<span class="token punctuation">(</span>article<span class="token punctuation">.</span>body<span class="token punctuation">,</span>
        extensions<span class="token operator">=</span><span class="token punctuation">[</span>
        <span class="token comment" spellcheck="true"># 包含 缩写、表格等常用扩展</span>
        <span class="token string">'markdown.extensions.extra'</span><span class="token punctuation">,</span>
        <span class="token comment" spellcheck="true"># 语法高亮扩展</span>
        <span class="token string">'markdown.extensions.codehilite'</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true"># 这里需要注意，原本的文本格式的文章现在转化成了html代码，如果要展示到前端，就要对数据进行转义</span>
<span class="token comment" spellcheck="true"># 复习:转义的两种方式</span>

<span class="token number">1</span> 直接在前端参数后面加safe过滤器
<span class="token operator">&lt;</span>p<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> article<span class="token punctuation">.</span>body<span class="token operator">|</span>safe <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>p<span class="token operator">></span>

<span class="token number">2</span> 在后端给html代码做标记
<span class="token keyword">from</span> django<span class="token punctuation">.</span>utils<span class="token punctuation">.</span>safestring <span class="token keyword">import</span> mark_safe
res <span class="token operator">=</span> mark_safe<span class="token punctuation">(</span>article<span class="token punctuation">.</span>body<span class="token punctuation">)</span>
</code></pre>
<h3 id="2、queryset对象"><a href="#2、queryset对象" class="headerlink" title="2、queryset对象"></a>2、queryset对象</h3><h4 id="2-1-可切片"><a href="#2-1-可切片" class="headerlink" title="2.1 可切片"></a>2.1 可切片</h4><p>用python的切片语法去限制查询的数据条数</p>
<pre class=" language-python"><code class="language-python">Entry<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>all<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">5</span><span class="token punctuation">]</span>      <span class="token comment" spellcheck="true"># (LIMIT 5)</span>
Entry<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>all<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">:</span><span class="token number">10</span><span class="token punctuation">]</span>    <span class="token comment" spellcheck="true"># (OFFSET 5 LIMIT 5)</span></code></pre>
<p>不支持负的索引，切片返回的是一个新的查询集，是由原来的查询集筛选得到的。</p>
<h4 id="2-2-可迭代"><a href="#2-2-可迭代" class="headerlink" title="2.2 可迭代"></a>2.2 可迭代</h4><p>取出的是每一个数据对象</p>
<h4 id="2-3-惰性查询"><a href="#2-3-惰性查询" class="headerlink" title="2.3 惰性查询"></a>2.3 惰性查询</h4><p>简单来说就是如果只是把查询结果赋值给了一个变量，而没使用这个变量的话，查询语句是不会执行的，只有真正对数据进行操作了才会回过头来执行查询语句。</p>
<h4 id="2-4-缓存机制？"><a href="#2-4-缓存机制？" class="headerlink" title="2.4 缓存机制？"></a>2.4 缓存机制？</h4><h4 id="2-5-exists-与iterator-方法"><a href="#2-5-exists-与iterator-方法" class="headerlink" title="2.5 exists()与iterator()方法"></a>2.5 exists()与iterator()方法</h4><p><strong>exists</strong></p>
<pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># 由于简单的if判断也会把整个数据对象集放入cache中，但是我们不需要判断这么多就可以用到exists</span>

<span class="token keyword">if</span> 查询集<span class="token punctuation">.</span>exists<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token comment" spellcheck="true"># 相当于只从查询集中拿出一条数据进行判断</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span></code></pre>
<p><strong>iterator</strong></p>
<pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># 查询得到的数据集可能会非常大，一次性放入内存就会影响性能，我们可以通过iterator把数据集做成一个迭代器</span>
<span class="token comment" spellcheck="true"># 注意做成迭代器的特点，取完数据后数据需要重新查询，无法回头</span>
<span class="token comment" spellcheck="true"># 每次在内存中只会存在一个数据</span>
objs <span class="token operator">=</span> Book<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>all<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>iterator<span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p>上面两种方法都是为了防止出现cache，所以他可能会增多了我们对数据库的查询，没有完美的方法只有合适的方法。</p>
<h4 id="2-6-orm额外方法"><a href="#2-6-orm额外方法" class="headerlink" title="2.6 orm额外方法"></a>2.6 orm额外方法</h4><pre class=" language-python"><code class="language-python">model<span class="token punctuation">.</span>Student<span class="token punctuation">.</span>object<span class="token punctuation">.</span>update_or_create<span class="token punctuation">(</span>aa<span class="token operator">=</span>aa<span class="token punctuation">,</span>defaults<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">'bb=bb'</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true"># 拿第一个参数作为查询依据，如果存在则修改，如果不存在则新增</span></code></pre>
<h3 id="3-extra"><a href="#3-extra" class="headerlink" title="3 extra"></a>3 extra</h3><p>由于orm对mysql的封装程度太高，有些情况下我们需要用一些复杂的查询就可以通过extra来对查询注入新的sql语句</p>
<p>extra可以指定一个或多个 <code>参数</code>,例如 <code>select</code>, <code>where</code> or <code>tables</code>. 这些参数都不是必须的，但是你至少要使用一个!要注意这些额外的方式对不同的数据库引擎可能存在移植性问题.(因为你在显式的书写SQL语句),除非万不得已,尽量避免这样做</p>
<h4 id="4-1参数之select"><a href="#4-1参数之select" class="headerlink" title="4.1参数之select"></a>4.1参数之select</h4><p>The <code>select</code> 参数可以让你在 <code>SELECT</code> 从句中添加其他字段信息，它应该是一个字典，存放着属性名到 SQL 从句的映射。</p>
<pre class=" language-python"><code class="language-python">queryResult<span class="token operator">=</span>models<span class="token punctuation">.</span>Article
　　　　　　　　　　　<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>extra<span class="token punctuation">(</span>select<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">'is_recent'</span><span class="token punctuation">:</span> <span class="token string">"create_time > '2017-09-05'"</span><span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<p>结果集中每个 Entry 对象都有一个额外的属性is_recent, 它是一个布尔值，表示 Article对象的create_time 是否晚于2017-09-05.</p>
<p>练习：</p>
<pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># in sqlite:</span>
    article_obj<span class="token operator">=</span>models<span class="token punctuation">.</span>Article<span class="token punctuation">.</span>objects
　　　　　　　　　　　　　　<span class="token punctuation">.</span>filter<span class="token punctuation">(</span>nid<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span>
　　　　　　　　　　　　　　<span class="token punctuation">.</span>extra<span class="token punctuation">(</span>select<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">"standard_time"</span><span class="token punctuation">:</span><span class="token string">"strftime('%%Y-%%m-%%d',create_time)"</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
　　　　　　　　　　　　　　<span class="token punctuation">.</span>values<span class="token punctuation">(</span><span class="token string">"standard_time"</span><span class="token punctuation">,</span><span class="token string">"nid"</span><span class="token punctuation">,</span><span class="token string">"title"</span><span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>article_obj<span class="token punctuation">)</span>
    <span class="token comment" spellcheck="true"># &lt;QuerySet [{'title': 'MongoDb 入门教程', 'standard_time': '2017-09-03', 'nid': 1}]></span></code></pre>
<h4 id="4-2参数之where-tables"><a href="#4-2参数之where-tables" class="headerlink" title="4.2参数之where / tables"></a>4.2参数之<code>where</code> / <code>tables</code></h4><p>您可以使用<code>where</code>定义显式SQL <code>WHERE</code>子句 - 也许执行非显式连接。您可以使用<code>tables</code>手动将表添加到SQL <code>FROM</code>子句。</p>
<p><code>where</code>和<code>tables</code>都接受字符串列表。所有<code>where</code>参数均为“与”任何其他搜索条件。</p>
<p>举例来讲：</p>
<pre class=" language-python"><code class="language-python">queryResult<span class="token operator">=</span>models<span class="token punctuation">.</span>Article
　　　　　　　　　　　<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>extra<span class="token punctuation">(</span>where<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">'nid in (1,3) OR title like "py%" '</span><span class="token punctuation">,</span><span class="token string">'nid>2'</span><span class="token punctuation">]</span><span class="token punctuation">)</span></code></pre>
<pre class=" language-python"><code class="language-python">extra<span class="token punctuation">,</span> 额外查询条件以及相关表，排序

                models<span class="token punctuation">.</span>UserInfo<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>filter<span class="token punctuation">(</span>id__gt<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span>
                models<span class="token punctuation">.</span>UserInfo<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>all<span class="token punctuation">(</span><span class="token punctuation">)</span> 
                <span class="token comment" spellcheck="true"># id name age ut_id</span>


                models<span class="token punctuation">.</span>UserInfo<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>extra<span class="token punctuation">(</span>self<span class="token punctuation">,</span> select<span class="token operator">=</span>None<span class="token punctuation">,</span> where<span class="token operator">=</span>None<span class="token punctuation">,</span> params<span class="token operator">=</span>None<span class="token punctuation">,</span> tables<span class="token operator">=</span>None<span class="token punctuation">,</span> order_by<span class="token operator">=</span>None<span class="token punctuation">,</span> select_params<span class="token operator">=</span>None<span class="token punctuation">)</span>
                <span class="token comment" spellcheck="true"># a. 映射</span>
                    <span class="token comment" spellcheck="true"># select </span>
                    <span class="token comment" spellcheck="true"># select_params=None</span>
                    <span class="token comment" spellcheck="true"># select 此处 from 表</span>

                <span class="token comment" spellcheck="true"># b. 条件</span>
                    <span class="token comment" spellcheck="true"># where=None</span>
                    <span class="token comment" spellcheck="true"># params=None,</span>
                    <span class="token comment" spellcheck="true"># select * from 表 where 此处</span>

                <span class="token comment" spellcheck="true"># c. 表</span>
                    <span class="token comment" spellcheck="true"># tables</span>
                    <span class="token comment" spellcheck="true"># select * from 表,此处</span>

                <span class="token comment" spellcheck="true"># c. 排序</span>
                    <span class="token comment" spellcheck="true"># order_by=None</span>
                    <span class="token comment" spellcheck="true"># select * from 表 order by 此处</span>


                models<span class="token punctuation">.</span>UserInfo<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>extra<span class="token punctuation">(</span>
                    select<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">'newid'</span><span class="token punctuation">:</span><span class="token string">'select count(1) from app01_usertype where id>%s'</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
                    select_params<span class="token operator">=</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
                    where <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'age>%s'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
                    params<span class="token operator">=</span><span class="token punctuation">[</span><span class="token number">18</span><span class="token punctuation">,</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
                    order_by<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">'-age'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
                    tables<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">'app01_usertype'</span><span class="token punctuation">]</span>
                <span class="token punctuation">)</span>
                <span class="token triple-quoted-string string">"""
                select 
                    app01_userinfo.id,
                    (select count(1) from app01_usertype where id>1) as newid
                from app01_userinfo,app01_usertype
                where 
                    app01_userinfo.age > 18
                order by 
                    app01_userinfo.age desc
                """</span>

                result <span class="token operator">=</span> models<span class="token punctuation">.</span>UserInfo<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>filter<span class="token punctuation">(</span>id__gt<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span>extra<span class="token punctuation">(</span>
                    where<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">'app01_userinfo.id &lt; %s'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
                    params<span class="token operator">=</span><span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
                    tables<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">'app01_usertype'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
                    order_by<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">'-app01_userinfo.id'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
                    select<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">'uid'</span><span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string">'sw'</span><span class="token punctuation">:</span><span class="token string">"select count(1) from app01_userinfo"</span><span class="token punctuation">}</span>
                <span class="token punctuation">)</span>
                <span class="token keyword">print</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>query<span class="token punctuation">)</span>
                <span class="token comment" spellcheck="true"># SELECT (1) AS "uid", (select count(1) from app01_userinfo) AS "sw", "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" FROM "app01_userinfo" , "app01_usertype" WHERE ("app01_userinfo"."id" > 1 AND (app01_userinfo.id &lt; 100)) ORDER BY ("app01_userinfo".id) DESC</span>
</code></pre>
<h2 id="三、路由部分"><a href="#三、路由部分" class="headerlink" title="三、路由部分"></a>三、路由部分</h2><h3 id="1-url和path的区别"><a href="#1-url和path的区别" class="headerlink" title="1 url和path的区别"></a>1 url和path的区别</h3><p>django1.x版本用的是url</p>
<p>基本用法：</p>
<pre class=" language-python"><code class="language-python"><span class="token keyword">from</span> django<span class="token punctuation">.</span>conf<span class="token punctuation">.</span>urls <span class="token keyword">import</span> url，include
<span class="token comment" spellcheck="true"># 参数部分是放一个{}内部键值对的key在views函数内要以关键字参数接受</span>
<span class="token comment" spellcheck="true"># 别名用于反向解析</span>
urlpatterns <span class="token operator">=</span> <span class="token punctuation">[</span>
     url<span class="token punctuation">(</span>正则表达式<span class="token punctuation">,</span> views视图函数，参数，别名<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span>

<span class="token comment" spellcheck="true"># 有名分组 year = 4位数的数字</span>
re_path<span class="token punctuation">(</span>r<span class="token string">'^articles/(?P&lt;year>[0-9]{4})/$'</span><span class="token punctuation">,</span> views<span class="token punctuation">.</span>year_archive<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token comment" spellcheck="true"># 无名分组</span>
re_path<span class="token punctuation">(</span>r<span class="token string">'^articles/([0-9]{4})/$'</span><span class="token punctuation">,</span> views<span class="token punctuation">.</span>year_archive<span class="token punctuation">)</span><span class="token punctuation">,</span>

<span class="token comment" spellcheck="true"># 路由分发</span>
path<span class="token punctuation">(</span><span class="token string">'app01/'</span><span class="token punctuation">,</span> include<span class="token punctuation">(</span>urls<span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment" spellcheck="true"># 反向解析的应用场景，当我们视图中或者模版中多次用到了某个url</span>
<span class="token comment" spellcheck="true"># 为了防止这个url后期修改导致所有用到的地方都要改，这里通过一个别名反向解析就行</span>
<span class="token comment" spellcheck="true"># 两种反向解析</span>

<span class="token comment" spellcheck="true"># 在视图函数中</span>
<span class="token keyword">from</span> django<span class="token punctuation">.</span>shortcuts <span class="token keyword">import</span> reverse
url <span class="token operator">=</span> reverse<span class="token punctuation">(</span><span class="token string">'tag'</span><span class="token punctuation">,</span>args<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token operator">/</span>mytag_test<span class="token operator">/</span><span class="token number">1</span>
<span class="token comment" spellcheck="true"># 得到的是url路径，args是拼接在后面的参数</span>

<span class="token comment" spellcheck="true"># 在页面中</span>
<span class="token punctuation">{</span><span class="token operator">%</span> url <span class="token string">"别名"</span> 参数  参数<span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>django2.x用的大部分是path，也可以导入url去使用，也有结合两种特性的re_path</p>
<pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># path的第一个是一个写死的路径，不支持正则</span>
<span class="token comment" spellcheck="true"># 第二个参数是具体的视图函数</span>
<span class="token comment" spellcheck="true"># 也可以反向解析</span>
<span class="token comment" spellcheck="true"># 在1.x版本的分组到2中变成了转换器拼接在url后面</span>
path<span class="token punctuation">(</span><span class="token string">'article-create/&lt;int:id>/'</span><span class="token punctuation">,</span> views<span class="token punctuation">.</span>article_create<span class="token punctuation">,</span> name<span class="token operator">=</span><span class="token string">'article_create'</span><span class="token punctuation">)</span>

<span class="token comment" spellcheck="true"># 内置了5中转化器</span>
str<span class="token punctuation">,</span>匹配除了路径分隔符（<span class="token operator">/</span>）之外的非空字符串，这是默认的形式
int<span class="token punctuation">,</span>匹配正整数，包含<span class="token number">0</span>。
slug<span class="token punctuation">,</span>匹配字母、数字以及横杠、下划线组成的字符串。
uuid<span class="token punctuation">,</span>匹配格式化的uuid，如 <span class="token number">075194d3</span><span class="token operator">-</span><span class="token number">6885</span><span class="token operator">-</span><span class="token number">417e</span><span class="token operator">-</span>a8a8<span class="token number">-6c931e272f00</span>。
path<span class="token punctuation">,</span>匹配任何非空字符串，包含了路径分隔符（<span class="token operator">/</span>）（不能用？）</code></pre>
<h2 id="四、模版部分"><a href="#四、模版部分" class="headerlink" title="四、模版部分"></a>四、模版部分</h2><h3 id="1-xss攻击"><a href="#1-xss攻击" class="headerlink" title="1 xss攻击"></a>1 xss攻击</h3><p>当我们服务端提供用户提交js代码的接口，就容易受到xss攻击，去用一些js代码影响我们的服务器。</p>
<p>如何解决xss攻击？</p>
<p>python中用了转义，让被设计者标记安全的语言才能显示到页面，内部原理是，如果用户给了<code>&lt;a href = &#39;meizitu.com&#39;&gt; 点击&lt;/a&gt;</code>这样的标签上传，如果标记安全，那这个字符串就会直接渲染到页面上变成一个标签。</p>
<p>如果我们没有对其转义，他会原封不动的显示在html页面上</p>
<p>展示的就是一些特殊字符，比如<code>&amp;gt</code>表示的就是&gt;，所以展示到页面的就是在后端显示的</p>
<h2 id="五、settings"><a href="#五、settings" class="headerlink" title="五、settings"></a>五、settings</h2><h3 id="1-静态资源暴露"><a href="#1-静态资源暴露" class="headerlink" title="1 静态资源暴露"></a>1 静态资源暴露</h3><p>网站所用的静态文件我们通常都放在static内，比如js，css文件，如果要让前端可以用这些静态文件渲染页面，就需要开放接口，关于网站的静态文件，django已经给我们开放了令牌（功能类似于反向解析），我们只要配置路径即可</p>
<pre class=" language-python"><code class="language-python">STATICFILES_DIRS <span class="token operator">=</span> <span class="token punctuation">[</span>
    os<span class="token punctuation">.</span>path<span class="token punctuation">.</span>join<span class="token punctuation">(</span>BASE_DIR<span class="token punctuation">,</span><span class="token string">'static'</span><span class="token punctuation">)</span>
<span class="token punctuation">]</span></code></pre>
<p>而用户上传的静态文件，也需要专门有一个文件夹来接收，通常我们用media做文件夹的名字，也可以修改</p>
<pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># settings.py</span>

MEDIA_ROOT <span class="token operator">=</span> os<span class="token punctuation">.</span>path<span class="token punctuation">.</span>join<span class="token punctuation">(</span>BASE_DIR<span class="token punctuation">,</span> <span class="token string">'media'</span><span class="token punctuation">)</span>  <span class="token comment" spellcheck="true"># 用户上传的文件就会保存到该文件夹下</span>
<span class="token comment" spellcheck="true"># media是文件夹的名字，可以自定义，一般使用media作为名字</span></code></pre>
<p>用户只要上传文件，就会自动创建media目录，会自动在media内创建相应的上传目录</p>
<p>例如models中，avatar字段</p>
<pre class=" language-python"><code class="language-python">avatar <span class="token operator">=</span> models<span class="token punctuation">.</span>FileField<span class="token punctuation">(</span>upload_to<span class="token operator">=</span><span class="token string">'avatar'</span><span class="token punctuation">,</span> default<span class="token operator">=</span><span class="token string">'avatar/default.png'</span><span class="token punctuation">)</span></code></pre>
<p>在上传了头像后，media内会自动创建一个avatar文件夹来存放头像</p>
<p>当然我们配置了路径只能在服务端使用这个路径，如果前端要访问后端的资源，就必须要开放相应的接口</p>
<p>在urls配置</p>
<p>固定写法，复制就能使用</p>
<pre class=" language-python"><code class="language-python"><span class="token keyword">from</span> django<span class="token punctuation">.</span>views<span class="token punctuation">.</span>static <span class="token keyword">import</span> serve
<span class="token keyword">from</span> bbs <span class="token keyword">import</span> settings
url<span class="token punctuation">(</span>r<span class="token string">'^media/(?P&lt;path>.*)'</span><span class="token punctuation">,</span> serve<span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token string">'document_root'</span><span class="token punctuation">:</span> settings<span class="token punctuation">.</span>MEDIA_ROOT<span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<h3 id="2-项目修改成中文"><a href="#2-项目修改成中文" class="headerlink" title="2 项目修改成中文"></a>2 项目修改成中文</h3><pre class=" language-python"><code class="language-python">LANGUAGE_CODE <span class="token operator">=</span> <span class="token string">'zh-hans'</span>

TIME_ZONE <span class="token operator">=</span> <span class="token string">'Asia/shanghai'</span>

USE_I18N <span class="token operator">=</span> <span class="token boolean">True</span>

USE_L10N <span class="token operator">=</span> <span class="token boolean">True</span>

USE_TZ <span class="token operator">=</span> <span class="token boolean">False</span>
</code></pre>
<h2 id="六、RBAC：基于角色的权限控制（django内置的auth体系）"><a href="#六、RBAC：基于角色的权限控制（django内置的auth体系）" class="headerlink" title="六、RBAC：基于角色的权限控制（django内置的auth体系）"></a>六、RBAC：基于角色的权限控制（django内置的auth体系）</h2><pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># RBAC :是基于角色的访问控制（Role-Based Access Control ）,公司内部系统</span>
<span class="token comment" spellcheck="true"># django的auth就是内置了一套基于RBAC的权限系统</span>

<span class="token comment" spellcheck="true"># django中</span>
    <span class="token comment" spellcheck="true"># 后台的权限控制（公司内部系统，crm，erp，协同平台）</span>
    user表  <span class="token comment" spellcheck="true">#用户表</span>
    permssion表 <span class="token comment" spellcheck="true"># 权限表</span>
    group表 <span class="token comment" spellcheck="true"># 组别表</span>
    user_groups表是user和group的中间表
    group_permissions表是group和permssion中间表
    user_user_permissions表是user和permission中间表
    <span class="token comment" spellcheck="true"># 前台（主站），需要用三大认证</span>

<span class="token comment" spellcheck="true"># 用户和组别是多对多</span>
用户a可以是销售组也可以是开发组
销售组也可以有多个人
<span class="token comment" spellcheck="true"># 组别和权限是多对多</span>
销售组的人有销售产品的权限，也有检查产品的权限
检查产品的权限可能管理组也有
<span class="token comment" spellcheck="true"># 用户和权限</span>
用户可以有多重权限
一个权限也可以有多个用户拥有</code></pre>
<h2 id="七、django的缓存"><a href="#七、django的缓存" class="headerlink" title="七、django的缓存"></a>七、django的缓存</h2><h3 id="1-缓存6中配置位置"><a href="#1-缓存6中配置位置" class="headerlink" title="1 缓存6中配置位置"></a>1 缓存6中配置位置</h3><ol>
<li><p>开发调试(此模式为开发调试使用,实际上不执行任何操作)</p>
</li>
<li><p>内存缓存</p>
<pre class=" language-python"><code class="language-python">CACHES <span class="token operator">=</span> <span class="token punctuation">{</span>
 <span class="token string">'default'</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
  <span class="token string">'BACKEND'</span><span class="token punctuation">:</span> <span class="token string">'django.core.cache.backends.locmem.LocMemCache'</span><span class="token punctuation">,</span>  <span class="token comment" spellcheck="true"># 指定缓存使用的引擎</span>
  <span class="token string">'LOCATION'</span><span class="token punctuation">:</span> <span class="token string">'unique-snowflake'</span><span class="token punctuation">,</span>         <span class="token comment" spellcheck="true"># 写在内存中的变量的唯一值 </span>
  <span class="token string">'TIMEOUT'</span><span class="token punctuation">:</span><span class="token number">300</span><span class="token punctuation">,</span>             <span class="token comment" spellcheck="true"># 缓存超时时间(默认为300秒,None表示永不过期)</span>
  <span class="token string">'OPTIONS'</span><span class="token punctuation">:</span><span class="token punctuation">{</span>
   <span class="token string">'MAX_ENTRIES'</span><span class="token punctuation">:</span> <span class="token number">300</span><span class="token punctuation">,</span>           <span class="token comment" spellcheck="true"># 最大缓存记录的数量（默认300）</span>
   <span class="token string">'CULL_FREQUENCY'</span><span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">,</span>          <span class="token comment" spellcheck="true"># 缓存到达最大个数之后，剔除缓存个数的比例，即：1/CULL_FREQUENCY（默认3）</span>
  <span class="token punctuation">}</span>  
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
</li>
<li><p>文件缓存</p>
</li>
<li><p>数据库缓存</p>
<pre class=" language-pythhon"><code class="language-pythhon">CACHES = {
 'default': {
  'BACKEND': 'django.core.cache.backends.db.DatabaseCache',  # 指定缓存使用的引擎
  'LOCATION': 'cache_table',          # 数据库表    
  'OPTIONS':{
   'MAX_ENTRIES': 300,           # 最大缓存记录的数量（默认300）
   'CULL_FREQUENCY': 3,          # 缓存到达最大个数之后，剔除缓存个数的比例，即：1/CULL_FREQUENCY（默认3）
  }  
 }   
}</code></pre>
</li>
<li><p>Memcache缓存(使用python-memcached模块连接memcache)</p>
</li>
<li><p>Memcache缓存(使用pylibmc模块连接memcache)</p>
</li>
</ol>
<h3 id="2-缓存应用"><a href="#2-缓存应用" class="headerlink" title="2 缓存应用"></a>2 缓存应用</h3><p>Django提供了不同粒度的缓存,可以缓存某个页面,可以只缓存一个页面的某个部分,甚至可以缓存整个网站.</p>
<h4 id="2-1-视图中使用缓存"><a href="#2-1-视图中使用缓存" class="headerlink" title="2.1 视图中使用缓存"></a>2.1 视图中使用缓存</h4><pre class=" language-python"><code class="language-python"><span class="token keyword">from</span> django<span class="token punctuation">.</span>views<span class="token punctuation">.</span>decorators<span class="token punctuation">.</span>cache <span class="token keyword">import</span> cache_page
<span class="token keyword">import</span> time
<span class="token keyword">from</span> <span class="token punctuation">.</span>models <span class="token keyword">import</span> <span class="token operator">*</span>

@cache_page<span class="token punctuation">(</span><span class="token number">15</span><span class="token punctuation">)</span>          <span class="token comment" spellcheck="true">#超时时间为15秒</span>
<span class="token keyword">def</span> <span class="token function">index</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">:</span>
　　t<span class="token operator">=</span>time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span>      <span class="token comment" spellcheck="true">#获取当前时间</span>
　　bookList<span class="token operator">=</span>Book<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>all<span class="token punctuation">(</span><span class="token punctuation">)</span>
　　<span class="token keyword">return</span> render<span class="token punctuation">(</span>request<span class="token punctuation">,</span><span class="token string">"index.html"</span><span class="token punctuation">,</span>locals<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>


<span class="token comment" spellcheck="true"># index.html</span>
<span class="token operator">&lt;</span>body<span class="token operator">></span>
<span class="token operator">&lt;</span>h3<span class="token operator">></span>当前时间<span class="token punctuation">:</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token punctuation">{</span><span class="token punctuation">{</span> t <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>h3<span class="token operator">></span>

<span class="token operator">&lt;</span>ul<span class="token operator">></span>
    <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">for</span> book <span class="token keyword">in</span> bookList <span class="token operator">%</span><span class="token punctuation">}</span>
       <span class="token operator">&lt;</span>li<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> book<span class="token punctuation">.</span>name <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> book<span class="token punctuation">.</span>price <span class="token punctuation">}</span><span class="token punctuation">}</span>$<span class="token operator">&lt;</span><span class="token operator">/</span>li<span class="token operator">></span>
    <span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>ul<span class="token operator">></span>

<span class="token operator">&lt;</span><span class="token operator">/</span>body<span class="token operator">></span>
<span class="token comment" spellcheck="true"># 我们可以看到的效果是15秒内不管前端刷新了几次 t都不会改变</span></code></pre>
<h4 id="2-2-全局使用缓存"><a href="#2-2-全局使用缓存" class="headerlink" title="2.2 全局使用缓存"></a>2.2 全局使用缓存</h4><p>既然是全站缓存,当然要使用Django中的中间件.</p>
<p>用户的请求通过中间件,经过一系列的认证等操作,如果请求的内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户</p>
<p>当返回给用户之前,判断缓存中是否已经存在,如果不存在,则UpdateCacheMiddleware会将缓存保存至Django的缓存之中,以实现全站缓存</p>
<pre class=" language-python"><code class="language-python">缓存整个站点，是最简单的缓存方法

在 MIDDLEWARE_CLASSES 中加入 “update” 和 “fetch” 中间件
MIDDLEWARE_CLASSES <span class="token operator">=</span> <span class="token punctuation">(</span>
    ‘django<span class="token punctuation">.</span>middleware<span class="token punctuation">.</span>cache<span class="token punctuation">.</span>UpdateCacheMiddleware’<span class="token punctuation">,</span> <span class="token comment" spellcheck="true">#第一</span>
    <span class="token string">'django.middleware.common.CommonMiddleware'</span><span class="token punctuation">,</span>
    ‘django<span class="token punctuation">.</span>middleware<span class="token punctuation">.</span>cache<span class="token punctuation">.</span>FetchFromCacheMiddleware’<span class="token punctuation">,</span> <span class="token comment" spellcheck="true">#最后</span>
<span class="token punctuation">)</span>
“update” 必须配置在第一个
“fetch” 必须配置在最后一个
<span class="token comment" spellcheck="true"># 视图和模版都不需要配置</span></code></pre>
<h4 id="2-3-局部视图缓存"><a href="#2-3-局部视图缓存" class="headerlink" title="2.3 局部视图缓存"></a>2.3 局部视图缓存</h4><pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># views</span>
<span class="token keyword">from</span> django<span class="token punctuation">.</span>views<span class="token punctuation">.</span>decorators<span class="token punctuation">.</span>cache <span class="token keyword">import</span> cache_page
<span class="token keyword">import</span> time
<span class="token keyword">from</span> <span class="token punctuation">.</span>models <span class="token keyword">import</span> <span class="token operator">*</span>
<span class="token keyword">def</span> <span class="token function">index</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">:</span>
     t<span class="token operator">=</span>time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span>      <span class="token comment" spellcheck="true">#获取当前时间</span>
     bookList<span class="token operator">=</span>Book<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>all<span class="token punctuation">(</span><span class="token punctuation">)</span>
     <span class="token keyword">return</span> render<span class="token punctuation">(</span>request<span class="token punctuation">,</span><span class="token string">"index.html"</span><span class="token punctuation">,</span>locals<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment" spellcheck="true"># index.html</span>
<span class="token punctuation">{</span><span class="token operator">%</span> load cache <span class="token operator">%</span><span class="token punctuation">}</span>
<span class="token punctuation">{</span><span class="token operator">%</span> cache <span class="token number">2</span> <span class="token string">'name'</span> <span class="token operator">%</span><span class="token punctuation">}</span>
 <span class="token operator">&lt;</span>h3<span class="token operator">></span>缓存<span class="token punctuation">:</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token punctuation">:</span><span class="token punctuation">{</span><span class="token punctuation">{</span> t <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>h3<span class="token operator">></span>
<span class="token punctuation">{</span><span class="token operator">%</span> endcache <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
</div><div id="reward-container"><span class="hty-icon-button button-glow" id="reward-button" title="打赏" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === &quot;none&quot;) ? &quot;block&quot; : &quot;none&quot;;"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-hand-coin-line"></use></svg></span><div id="reward-comment">点我就给你看点有意思的</div><div id="qr" style="display:none;"><div style="display:inline-block"><a target="_blank" rel="noopener" href="https://gitee.com/huang_zhao/hz/raw/master/hz/alipay.png"><img loading="lazy" src="https://gitee.com/huang_zhao/hz/raw/master/hz/alipay.png" alt="支付宝" title="支付宝"></a><div><span style="color:#00A3EE"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-alipay-line"></use></svg></span></div></div><div style="display:inline-block"><a target="_blank" rel="noopener" href="https://gitee.com/huang_zhao/hz/raw/master/hz/qqpay.jpg"><img loading="lazy" src="https://gitee.com/huang_zhao/hz/raw/master/hz/qqpay.jpg" alt="QQ 支付" title="QQ 支付"></a><div><span style="color:#12B7F5"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-qq-line"></use></svg></span></div></div><div style="display:inline-block"><a target="_blank" rel="noopener" href="https://gitee.com/huang_zhao/hz/raw/master/hz/wxpay.jpg"><img loading="lazy" src="https://gitee.com/huang_zhao/hz/raw/master/hz/wxpay.jpg" alt="微信支付" title="微信支付"></a><div><span style="color:#2DC100"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-wechat-pay-line"></use></svg></span></div></div></div></div><ul class="post-copyright"><li class="post-copyright-author"><strong>本文作者：</strong>爱肖彤真是太好了</li><li class="post-copyright-link"><strong>本文链接：</strong><a href="http://huang_zhao.gitee.io/task/2021/05/15/python/%E6%A1%86%E6%9E%B6/django%20%E7%9F%A5%E8%AF%86%E7%82%B9%E6%89%A9%E5%B1%95/" title="django知识点扩展">http://huang_zhao.gitee.io/task/2021/05/15/python/%E6%A1%86%E6%9E%B6/django%20%E7%9F%A5%E8%AF%86%E7%82%B9%E6%89%A9%E5%B1%95/</a></li><li class="post-copyright-license"><strong>版权声明：</strong>本博客所有文章除特别声明外，均默认采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="noopener" title="CC BY-NC-SA 4.0 "><svg class="icon"><use xlink:href="#icon-creative-commons-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-by-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-nc-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-sa-line"></use></svg></a> 许可协议。</li></ul></section></article><div class="post-nav"><div class="post-nav-item"><a class="post-nav-prev" href="/task/2021/06/27/%E6%95%B0%E6%8D%AE%E5%BA%93/redis/Redis/" rel="prev" title="Redis"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-left-s-line"></use></svg><span class="post-nav-text">Redis</span></a></div><div class="post-nav-item"><a class="post-nav-next" href="/task/2021/03/15/%E5%85%B6%E4%BB%96/linux%E5%AD%A6%E4%B9%A0/" rel="next" title="linux学习"><span class="post-nav-text">linux学习</span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-right-s-line"></use></svg></a></div></div></div></main><footer class="sidebar-translate" id="footer"><div class="copyright"><span>&copy; 2019 – 2022 </span><span class="with-love" id="animate"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-cloud-line"></use></svg></span><span class="author"> 爱肖彤真是太好了</span></div><div class="powered"><span>由 <a href="https://hexo.io" target="_blank" rel="noopener">Hexo</a> 驱动 v5.1.1</span><span class="footer-separator">|</span><span>主题 - <a rel="noopener" href="https://github.com/YunYouJun/hexo-theme-yun" target="_blank"><span>Yun</span></a> v0.9.7</span></div><div class="live_time"><span>本博客已萌萌哒地运行</span><span id="display_live_time"></span><span class="moe-text">(●'◡'●)</span><script>function blog_live_time() {
  window.setTimeout(blog_live_time, 1000);
  const start = new Date('2019-04-12T00:00:00');
  const now = new Date();
  const timeDiff = (now.getTime() - start.getTime());
  const msPerMinute = 60 * 1000;
  const msPerHour = 60 * msPerMinute;
  const msPerDay = 24 * msPerHour;
  const passDay = Math.floor(timeDiff / msPerDay);
  const passHour = Math.floor((timeDiff % msPerDay) / 60 / 60 / 1000);
  const passMinute = Math.floor((timeDiff % msPerHour) / 60 / 1000);
  const passSecond = Math.floor((timeDiff % msPerMinute) / 1000);
  display_live_time.innerHTML = " " + passDay + " 天 " + passHour + " 小时 " + passMinute + " 分 " + passSecond + " 秒";
}
blog_live_time();
</script></div><div id="busuanzi"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span id="busuanzi_container_site_uv" title="总访客量"><span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-user-line"></use></svg></span><span id="busuanzi_value_site_uv"></span></span><span class="footer-separator">|</span><span id="busuanzi_container_site_pv" title="总访问量"><span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-eye-line"></use></svg></span><span id="busuanzi_value_site_pv"></span></span></div></footer><a class="hty-icon-button" id="goUp" aria-label="back-to-top" href="#"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-up-s-line"></use></svg><svg class="progress-circle-container" viewBox="0 0 100 100"><circle class="progress-circle" id="progressCircle" cx="50" cy="50" r="48" fill="none" stroke="#0078E7" stroke-width="2" stroke-linecap="round"></circle></svg></a><a class="popup-trigger hty-icon-button icon-search" id="search" href="javascript:;" title="搜索"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-search-line"></use></svg></span></a><script>window.addEventListener("DOMContentLoaded", () => {
  // Handle and trigger popup window
  document.querySelector(".popup-trigger").addEventListener("click", () => {
    document.querySelector(".popup").classList.add("show");
    setTimeout(() => {
      document.querySelector(".search-input").focus();
    }, 100);
  });

  // Monitor main search box
  const onPopupClose = () => {
    document.querySelector(".popup").classList.remove("show");
  };

  document.querySelector(".popup-btn-close").addEventListener("click", () => {
    onPopupClose();
  });

  window.addEventListener("keyup", event => {
    if (event.key === "Escape") {
      onPopupClose();
    }
  });
});
</script><script src="/task/js/search/local-search.js" defer></script><div class="popup search-popup"><div class="search-header"><span class="popup-btn-close close-icon hty-icon-button"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-close-line"></use></svg></span></div><div class="search-input-container"><input class="search-input" id="local-search-input" type="text" placeholder="搜索..." value=""></div><div id="local-search-result"></div></div></div><script defer src="/task/js/utils.js"></script><script defer src="/task/js/hexo-theme-yun.js"></script></body></html>